home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
prog_c
/
kbstf10.zip
/
KBSTUFFR.C
< prev
next >
Wrap
Text File
|
1996-01-31
|
18KB
|
454 lines
#ifndef __TINY__
#error Must be compiled in tiny model
#endif
#define NULL 0
#if __STDC__
#define _Cdecl
#else
#define _Cdecl cdecl
#endif
void _Cdecl __cli__ (void);
void _Cdecl __sti__ (void);
void _Cdecl __int__(int interruptnum);
/* extern unsigned _Cdecl _psp; */
/* *********************************************************************** */
/* The little assembly TSR KBSTFRES.COM hooks INT 1Ch (user interrupt), */
/* complying with IBM's INTERRUPT-SHARING PROTOCOL and stuffs the key- */
/* board buffer with the 2-bytes words it finds in his internal buffer. */
/* This 2-bytes words are in general formed by the ASCII translation in */
/* the low byte and the scan code in the high byte. Extended characters */
/* could have an ASCII translation of 0 or E0 (for the extended 101/102 */
/* keys keyboards) or F0 (other extended chars). You can inspect keys */
/* stored in the keyboard buffer from the standard INT 9h handler with */
/* the program SEEKBBUF.COM (with Turbo-c source). */
/* A word with value 0 shouldn't never be generated by standard INT 9h */
/* handler and so the TSR interprets a 0 in his buffer as a request of a */
/* pause, and the following word represent for it the number of clock- */
/* ticks to wait. A 0 as number of ticks is interpreted as 65536. */
/* Even a word with the high byte equals to 0xFF should never be gene- */
/* rated by the standard INT 9h handler and so the TSR interprets this */
/* as a "short pause", the low byte representing the number of thicks, 0 */
/* interpreted again as 65536. */
/* The KBSTFRES.COM's buffer is a circular buffer similarly to the key- */
/* board buffer, but it's bigger and could be made even bigger, alloca- */
/* ting memory, even if the TSR is already installed. */
/* The KBSTFRES.COM's companion program KBSTUFFR.COM is used to store */
/* keys in the TSR's buffer. It could be even used as a scheme for ad- */
/* ding other options as allocating another buffer. */
/* */
/* The way to use KBSTUFFR is simple for c programmers. */
/* syntax: */
/* KBSTUFFR [/R] [/U] [/G] [/S] <what to stuff> */
/* /R Option. If present must be the first parameter, other- */
/* wise is interpreted as two characters to store. */
/* Reset the TSR's buffer. */
/* /U Option. If present must be the first parameter, other- */
/* wise is interpreted as two characters to store. */
/* Whatever follow this option is obviously ignored. */
/* Uninstall the TSR and remove it from memory. */
/* /R and /U options are mutually excluding. Both must be the */
/* first option. The use of both is, however, a nonsense. */
/* /S Stops the TSR. |_ Can appear anywhere outside of */
/* /G Restarts the TSR. | C-strings */
/* <what to stuff> are the characters to store in the buffer. */
/* Blanks and tabs are generally skipped, but you can use */
/* a C-type string, as, for example, */
/* "pippo a:\r" */
/* "\r\n\t\aError in C:\\work\r\n" */
/* "\76\xFDThis are octal and hexadecimal notation\?" */
/* \OOO and \xHHH are accepted as for ANSI C, but if the */
/* value of FFh is exceeded only the low byte is conside- */
/* red and the high is stripped. */
/* With this "normal" use only ASCII translation are sto- */
/* red, without scan code, as the keys would have been ge- */
/* nerated with the ALT-key+Keypad numbers combination. */
/* My extensions to C-string allow to store extended keys */
/* with a low byte of 0 and special pause sequences. */
/* To store the word 6800h, for example, many methods can */
/* be used: */
/* "\0\x68","\ex68" (where the escape sequence \e is an */
/* extension to the standard C-string syntax), "\0h" or */
/* "\eh" (where ascii('h')=0x68) */
/* The x is used as an escape character for the \e escape */
/* sequence, so if 7800h(=<ALT 1>) has to be stored can be */
/* used: */
/* "\ex78","\0\x78","\0x" or "\exx" */
/* To store a pause, the other extension "\pDDDDD" has to */
/* be used where DDDDD is a decimal number. If only "\p" */
/* or "\p0" is entered the pause is set to the default of */
/* 1 clock-tick. */
/* */
/* Thanks a lot to Chris Dunford for posting informations about IBM's */
/* INTERRUPT-SHARING PROTOCOL */
/* */
/* */
/* (c) 1996 by Luigi Mancinelli */
/* manci@alpha.science.unitn.it */
/* */
/* Note: If the program has to be recompiled, the tiny model has to be */
/* used and the resulting .exe has to be converted in .com (with the DOS */
/* utility EXE2BIN for example) or the program doesn't work. */
/* */
/* *********************************************************************** */
#define MK_FP(seg,ofs) ((void far *) \
(((unsigned long)(seg) << 16) | (unsigned)(ofs)))
#define SET_FP_OFF(fp,ofs) ((void far *) \
((((unsigned long)(fp))&0xFFFF0000)|(unsigned)(ofs)))
#define FAR_BYTE(fp) (*((unsigned char far *) (fp)))
#define FAR_ULONG(fp) (*((unsigned long far *) (fp)))
#define _toupper(c) ((c)&0xDF)
#define putchar(c) (_DL=c,_AH=02,__int__(0x21))
#define putbackslash() (_DL='\\',_AH=02,__int__(0x21))
void putstring(char *p)
{ unsigned int i=0;
if (p!=NULL)
while (p[i]!=0) putchar(p[i++]);
}
char *HexDig="0123456789ABCDEF";
void puthexbyte(unsigned char ch)
{
putchar(HexDig[ch>>4]);
putchar(HexDig[ch&0xF]);
}
void puthexword(unsigned int w)
{
puthexbyte( ((unsigned char *) &w)[1] );
puthexbyte( *((unsigned char *) &w) );
}
void putpntr(void far *p)
{
puthexword( ((unsigned int *) &p)[1] );
putchar(':');
puthexword( *((unsigned int *) &p) );
}
void newline(void)
{ putchar('\r'); putchar('\n'); }
int IsGoodSeparator(unsigned char Ch)
{ return (Ch==0x0D)||(Ch==' ')||(Ch==9)||(Ch=='"'); }
typedef struct TSRPROTSTRU {
unsigned int ShortJmp;
struct TSRPROTSTRU far * Old;
unsigned int Signature;
char flag;
unsigned int ShortJmpHWreset;
char bytes[7];
unsigned int MyJump;
char recognise[5];
char retf;
unsigned int bufseg;
unsigned int bufstart;
unsigned int bufend;
unsigned int bufhead;
unsigned int buftail;
unsigned char IsActive;
unsigned char IsInError;
unsigned char IsInPause;
unsigned char IsStopped;
} TsrProtStructure;
typedef TsrProtStructure far *TsrProt;
TsrProt GetVect(unsigned char i)
{
_AH=0x35; _AL=i; /* _AX=0x3500 | i; */
__int__(0x21);
return (TsrProt) MK_FP(_ES,_BX);
}
void SetVect(unsigned char i, TsrProt P)
{
unsigned int SaveDS;
SaveDS=_DS;
_DX=*((unsigned int *)(&P));
_DS=((unsigned int *)(&P))[1];
_AL=i; _AH=0x25; /* _AX=0x2500 | i; */
__int__(0x21);
_DS=SaveDS;
return;
}
#define SEG_OF_FARP(FP) (((unsigned int *)(&(FP)))[1])
#define FreeDOSMem(SEG) (_ES=SEG,_AH=0x49,__int__(0x21))
int IsCorrectTsrProtStru(TsrProt P)
{
if (P==NULL) return 0;
else if (P->Signature!=0x424B) return 0;
/* comment following line for a less strict control */
else if (P->ShortJmp!=0x10EB) return 0;
else return 1;
}
int IsKBSTFRES(TsrProt P)
{
if (IsCorrectTsrProtStru(P)==0) return -1;
else if ((P->recognise[0]=='K')&&(P->recognise[1]=='B')&&
(P->recognise[2]=='S')&&(P->recognise[3]=='T')&&
(P->recognise[4]=='F') ) return 1;
else return 0;
}
TsrProt Pntr;
TsrProt OldPntr=NULL;
#define FULL 1
#define STRING 2
#define EXTCHAR 4
#define PAUSE 8
#define SWITCHFOUND 128
unsigned int p,n;
unsigned int far * FarP;
unsigned char Ch,c;
unsigned int Word;
unsigned long int Ticks;
char Flags=0;
char *ToNewPtr=" => ";
char *Mess="Stuffed ...\"";
char *CheckMess="Actual int 1Ch handler => ";
char *ErrMess="Cannot inspect TSR chain - KBSTFRES not found\r\n";
char *Going="OK";
char *Stopped="STOPPED";
char *TryUnInst="Attempting to uninstalling KBSTFRES\r\n";
char *Win="In DOS Windows ";
char *NotUnInWin="Unable to uninstall from a DOS Windows\r\n";
char *Uninstalled="KBSTFRES successfully uninstalled\r\n";
char *Re_Chaining="Re-chaining to old interrupt ";
char *Restoring="Restoring old interrupt ";
/* *************************** */
unsigned char *CmdStr=(unsigned char *) 0x80;
int i=1;
void SkipBlanks(void) {
while ((CmdStr[i]==' ')||(CmdStr[i]==9)) i++;
}
/* *************************** */
int GetHexByte(void)
{
/* register c; */
unsigned int j=0;
Ch=0;
while((j++<3)&&
( (((c=CmdStr[i])>='0')&&(c<='9')) ||
(((c=_toupper(c))>='A')&&(c<='F')) ) ) {
if(c>='A') c-=('A'-10); else c-='0';
Ch=(Ch<<4)+c; i++;
}
}
main() {
/*
unsigned int DS=((unsigned long)((char far *)(&CmdStr)))>>16;
if(DS==_psp) { */
int Fnd;
/* now try to find KBSTFRES as int 1Ch handler */
Pntr=/* (TsrProt) getvect(0x1C) */ GetVect(0x1C);
putstring(CheckMess); putpntr(Pntr); newline();
if( (((unsigned int)(Pntr))==0x98)&&
(FAR_BYTE(SET_FP_OFF(Pntr,0xB7))==0x2E) &&
(FAR_ULONG(SET_FP_OFF(Pntr,0xB8))==0x00942EFF) ) {
/* is DOS Windows ? */
putstring(Win);
OldPntr=Pntr; Pntr=*((TsrProt far *)SET_FP_OFF(OldPntr,0x0094));
putpntr(OldPntr); putstring(ToNewPtr); putpntr(Pntr); newline();
OldPntr=(TsrProt) 0xFFFFFFFF;
}
while ((Fnd=IsKBSTFRES(Pntr))==0) {
OldPntr=Pntr; Pntr=Pntr->Old;
putpntr(OldPntr); putstring(ToNewPtr); putpntr(Pntr); newline();
}
if(Fnd==-1) {
putstring(ErrMess);
return 1;
}
else {
(Pntr->IsActive)++;
while (Pntr->IsActive>1) /* wait exit from 1Ch handler */
{ putchar(Pntr->IsActive+48); putchar('\r'); }
((unsigned int *)(&FarP))[1]=Pntr->bufseg;
p=CmdStr[0]; if(CmdStr[p+1]!=0x0D) CmdStr[p+1]=0x0D;
SkipBlanks();
if((CmdStr[i]=='/')&&
((_toupper(CmdStr[i+1])=='U')||(_toupper(CmdStr[i+1])=='R'))&&
(IsGoodSeparator(CmdStr[i+2])) ) {
if (_toupper(CmdStr[i+1])=='U') {
if (((unsigned long) OldPntr)==0xFFFFFFFF) {
Pntr->IsStopped=1;
Pntr->bufhead=Pntr->buftail=Pntr->bufstart;
Pntr->IsInPause=0;
(Pntr->IsActive)--;
putstring(NotUnInWin);
return 2;
}
else {
/* now try to unhook int 1Ch */
putstring(TryUnInst);
if (OldPntr!=NULL) { /* adjust the after loaded TSR */
putstring(Re_Chaining);
__cli__();
OldPntr->Old=Pntr->Old;
__sti__();
}
else {
putstring(Restoring);
SetVect(0x1C,Pntr->Old);
}
putpntr(Pntr->Old); newline();
FreeDOSMem(SEG_OF_FARP(Pntr));
putstring(Uninstalled);
return 0;
}
}
else {
Pntr->bufhead=Pntr->buftail=Pntr->bufstart;
Pntr->IsInPause=0;
i+=2; SkipBlanks();
}
}
putstring(Mess);
/* printf("Stuffed...\""); */
while (((Ch=CmdStr[i++])!=0x0D)&&((Flags & FULL)==0)) {
if((Ch=='"')&&(Flags & STRING)) Flags&=~STRING & ~EXTCHAR;
else {
if(Ch=='"') {
register j=i; Ch=CmdStr[i++];
while ((CmdStr[j]!=0x0D)&&
((CmdStr[j]!='"')||(CmdStr[j-1]=='\\'))) j++;
if(CmdStr[j]==0x0D) break; else Flags|=STRING;
}
if((Flags & STRING)&&(Ch=='\\')) {
if(((Ch=CmdStr[i++])>='0')&&(Ch<='7')) {
register j=1; /* register c; */
Ch-='0';
while((j++<3)&&(((c=CmdStr[i])>='0')&&(c<='7')) )
{ Ch=(Ch<<3)+(c-'0'); i++; }
}
else switch (Ch) {
/* My extensions to normal C string syntax */
case 'p':{
register c; register unsigned int j=0;
Ch='p'; Ticks=0;
while((j++<5)&&
(((c=CmdStr[i])>='0')&&(c<='9')) )
{ Ticks=(Ticks<<3)+(Ticks<<1)+(c-'0'); i++; }
}
if(Ticks>65536) Ticks=65536;
else if(Ticks==0) Ticks=1;
Flags|=PAUSE;
break;
case 'e':Ch=0;
if(CmdStr[i]=='x') {
Flags|=EXTCHAR;
if(CmdStr[++i]=='x') { Ch='x'; i++; }
else GetHexByte();
}
break;
/* normal C string syntax */
case 'a':Ch=7; break;
case 'b':Ch=8; break;
case 'f':Ch=0x0C; break;
case 'n':Ch=0x0A; break;
case 'r':Ch=0x0D; break;
case 't':Ch=0x09; break;
case 'v':Ch=0x0B; break;
case 'X':
case 'x':GetHexByte();
break;
case '\'':
case '\?':
case '"':
case '\\':break;
}
}
else if(Ch=='/')
switch (_toupper(CmdStr[i])) {
case 'S':
case 'G':if(IsGoodSeparator(CmdStr[i+1])) {
Pntr->IsStopped=(CmdStr[i++]=='S');
Flags|=SWITCHFOUND;
SkipBlanks();
}
break;
}
if (Flags & SWITCHFOUND) Flags&=~SWITCHFOUND;
else if(Ch==0) Flags|=EXTCHAR;
else {
if((n=p=Pntr->buftail+2)==Pntr->bufend) p=Pntr->bufstart;
if(Flags & PAUSE) {
if((n+=2)==Pntr->bufend) n=Pntr->bufstart;
}
if((p!=Pntr->bufhead)&&(n!=Pntr->bufhead)) {
if(Flags & PAUSE) {
register unsigned int j=10000;
Word=Ticks; Flags&=~PAUSE;
putbackslash(); putchar('p');
while ((Ch=(Ticks/j))==0) j/=10;
putchar(Ch+'0'); Ticks-=Ch*j;
while (j>1) {
putchar((Ch=Ticks/j)+'0');
Ticks-=Ch*j; j/=10;
}
if (Word<256) Word|=0xFF00;
else {
*((unsigned int *)(&FarP))= Pntr->buftail;
(*FarP)=0; Pntr->buftail=p; p=n;
}
}
else {
if(Flags & EXTCHAR) {
Word=((unsigned int) Ch)<<8;
putbackslash(); putchar('e');
if(Ch=='x') putchar('x');
}
else Word=Ch & 0xFF;
if(Ch=='\\') putbackslash();
else if((Ch>=32)&&(Ch!=127)&&(Ch!=255)) putchar(Ch);
else {
if((Flags & EXTCHAR)==0) putbackslash();
putchar('x');
puthexbyte(Ch);
}
}
*((unsigned int *)(&FarP))= Pntr->buftail;
(*FarP)=Word;
Pntr->buftail=p;
} else Flags|=FULL;
Flags&=~EXTCHAR;
}
}
if ((Flags & STRING)==0) SkipBlanks();
}
putchar('"'); newline();
if(Pntr->IsStopped) putstring(Stopped); else putstring(Going);
newline();
(Pntr->IsActive)--;
}
/* } */
}